﻿/**
 * @file std_stack.h
 * Copyright (c) 2019 Gaaagaa. All rights reserved.
 * 
 * @author  : Gaaagaa
 * @date    : 2019-09-09
 * @version : 1.0.0.0
 * @brief   : 使用 C API 的接口形式实现 栈 容器。
 */

/**
 * The MIT License (MIT)
 * Copyright (c) Gaaagaa. All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef __STD_STACK_H__
#define __STD_STACK_H__

#include "std_comm.h"

////////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

////////////////////////////////////////////////////////////////////////////////

//====================================================================

// 
// xstd_stack_t 的相关数据类型定义
// 

#define XSTK_FALSE   XSTD_FALSE
#define XSTK_TRUE    XSTD_TRUE
#define XSTK_NULL    XSTD_NULL

typedef xstd_void_t  xstk_void_t;
typedef xstd_bool_t  xstk_bool_t;
typedef xstd_size_t  xstk_size_t;
typedef xstd_elem_t  xstk_elem_t;
typedef xstd_ctxt_t  xstk_ctxt_t;

/** 声明 xstd_stack_t 对象指针类型 */
typedef struct xstd_stack_t * xstk_this_t;

//====================================================================

// 
// xstd_stack_t 的相关操作接口
// 

/**********************************************************/
/**
 * @brief 返回内部的 sizeof(xstd_stack_t) 值。
 */
xstk_size_t std_stack_sizeof(void);

/**********************************************************/
/**
 * @brief 创建 xstd_stack_t 对象。
 * @note  应使用 @see std_stack_destroy() 销毁所创建的对象。
 * 
 * @param [in ] xstk_ctxt : 队列 所存储的节点元素上下文描述信息。
 * 
 * @return xstk_this_t : 返回所创建的 xstd_stack_t 对象指针。
 */
xstk_this_t std_stack_create(xstk_ctxt_t xstk_ctxt);

/**********************************************************/
/**
 * @brief 
 * 销毁 xstd_stack_t 对象，
 * 其由 @see std_stack_create() 接口所创建。
 */
xstk_void_t std_stack_destroy(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 在指定的缓存上创建 xstd_stack_t 对象。
 * @note
 * 1. 所使用的缓存，其大小应不小于 @see std_stack_sizeof() 的返回值。
 * 2. 销毁对象时，应使用 @see std_stack_emplace_destroy() 接口。
 * 
 * @param [out] xstk_this : 创建 xstd_stack_t 对象使用的缓存。
 * @param [in ] xstk_ctxt : 队列 所存储的节点元素上下文描述信息。
 * 
 * @return xstk_this_t : 返回所创建的 xstd_stack_t 对象指针。
 */
xstk_this_t std_stack_emplace_create(
                    xstk_this_t xstk_this,
                    xstk_ctxt_t xstk_ctxt);

/**********************************************************/
/**
 * @brief 
 * 销毁 xstd_stack_t 对象，
 * 其由 @see std_stack_emplace_create() 接口所创建。
 */
xstk_void_t std_stack_emplace_destroy(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 返回 xstd_stack_t 对象的 上下文信息。
 */
xstk_ctxt_t std_stack_ctxt(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 返回 xstd_stack_t 对象的 类型标识。
 */
xstk_size_t std_stack_etype(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 返回 xstd_stack_t 对象当前的节点数量。
 */
xstk_size_t std_stack_size(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 判断 xstd_stack_t 对象是否为空。
 */
xstk_bool_t std_stack_empty(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 返回 xstd_stack_t 对象可容纳最大的节点数量。
 */
xstk_size_t std_stack_maxsize(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 返回 xstd_stack_t 对象的顶端节点元素。
 */
xstk_elem_t std_stack_top(xstk_this_t xstk_this);

/**********************************************************/
/**
 * @brief 向 xstd_stack_t 对象压入一个元素。
 * 
 * @param [in,out] xstk_this : xstd_stack_t 对象。
 * @param [in    ] xstk_elem : 所压入的元素值。
 */
xstk_void_t std_stack_push(
                xstk_this_t xstk_this,
                xstk_elem_t xstk_elem);

/**********************************************************/
/**
 * @brief 使用右值 move 方式，向 xstd_stack_t 对象压入一个元素。
 * 
 * @param [in,out] xstk_this : xstd_stack_t 对象。
 * @param [in    ] xstk_elem : 所压入的元素值。
 */
xstk_void_t std_stack_mpush(
                xstk_this_t xstk_this,
                xstk_elem_t xstk_elem);

/**********************************************************/
/**
 * @brief 对  xstd_stack_t 对象的顶端元素执行弹出（删除）操作。
 */
xstk_void_t std_stack_pop(xstk_this_t xstk_this);

////////////////////////////////////////////////////////////////////////////////

/** 
 * @brief 
 * 为 xstd_stack_t 的基础数据类型容器，
 * 定义简化版操作接口的宏。
 */
#define XSTD_STACK_TYPE_FUNC(xtype, xname)          \
                                                    \
static inline xstk_this_t                           \
    std_stack_create_##xname(void)                  \
{                                                   \
    return std_stack_create(&xstd_ctxt_##xname);    \
}                                                   \
                                                    \
static inline xtype                                 \
    std_stack_top_##xname(                          \
            xstk_this_t xstk_this)                  \
{                                                   \
    return *(xtype *)std_stack_top(xstk_this);      \
}                                                   \
                                                    \
static inline xstk_void_t                           \
    std_stack_push_##xname(                         \
            xstk_this_t xstk_this,                  \
            xtype xstk_elem)                        \
{                                                   \
    std_stack_push(xstk_this, &xstk_elem);          \
}                                                   \
                                                    \
static inline xstk_void_t                           \
    std_stack_pop_##xname(                          \
            xstk_this_t xstk_this)                  \
{                                                   \
    std_stack_pop(xstk_this);                       \
}

//====================================================================

XSTD_STACK_TYPE_FUNC(xstd_char_t   , char   )  // 对应 xstd_char_t    类型
XSTD_STACK_TYPE_FUNC(xstd_uchar_t  , uchar  )  // 对应 xstd_uchar_t   类型
XSTD_STACK_TYPE_FUNC(xstd_int8_t   , int8   )  // 对应 xstd_int8_t    类型
XSTD_STACK_TYPE_FUNC(xstd_int16_t  , int16  )  // 对应 xstd_int16_t   类型
XSTD_STACK_TYPE_FUNC(xstd_int32_t  , int32  )  // 对应 xstd_int32_t   类型
XSTD_STACK_TYPE_FUNC(xstd_int64_t  , int64  )  // 对应 xstd_int64_t   类型
XSTD_STACK_TYPE_FUNC(xstd_uint8_t  , uint8  )  // 对应 xstd_uint8_t   类型
XSTD_STACK_TYPE_FUNC(xstd_uint16_t , uint16 )  // 对应 xstd_uint16_t  类型
XSTD_STACK_TYPE_FUNC(xstd_uint32_t , uint32 )  // 对应 xstd_uint32_t  类型
XSTD_STACK_TYPE_FUNC(xstd_uint64_t , uint64 )  // 对应 xstd_uint64_t  类型
XSTD_STACK_TYPE_FUNC(xstd_long_t   , long   )  // 对应 xstd_long_t    类型
XSTD_STACK_TYPE_FUNC(xstd_llong_t  , llong  )  // 对应 xstd_llong_t   类型
XSTD_STACK_TYPE_FUNC(xstd_ulong_t  , ulong  )  // 对应 xstd_ulong_t   类型
XSTD_STACK_TYPE_FUNC(xstd_ullong_t , ullong )  // 对应 xstd_ullong_t  类型
XSTD_STACK_TYPE_FUNC(xstd_float_t  , float  )  // 对应 xstd_float_t   类型
XSTD_STACK_TYPE_FUNC(xstd_double_t , double )  // 对应 xstd_double_t  类型
XSTD_STACK_TYPE_FUNC(xstd_ldouble_t, ldouble)  // 对应 xstd_ldouble_t 类型
XSTD_STACK_TYPE_FUNC(xstd_handle_t , handle )  // 对应 xstd_handle_t  类型

////////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
}; // extern "C"
#endif // __cplusplus

////////////////////////////////////////////////////////////////////////////////

#endif // __STD_STACK_H__

